package qeug.shsh.bpm.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.apusic.juli.logging.Log;
import com.apusic.juli.logging.LogFactory;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.devportal.BizScriptServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Base64Utils;
import org.xml.sax.InputSource;
import qeug.shsh.bpm.annotation.ThridSrevice;
import qeug.shsh.bpm.service.IG6Service;
import qeug.shsh.helper.FacadeHelper;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @projectName: qeug-cosmic-root-project
 * @package: qeug.shsh.bpm.service.impl
 * @className: G6ServiceImpl
 * @author: wenyx
 * @description: TODO
 * @date: 2023/11/25 22:19
 * @version: 1.0
 * 说明：推送G6单据：费用报销单；差旅报销单；借款单；资金计划-月度支出计划，月度收入计划；付款申请单
 */
@ThridSrevice("G6ServiceImpl")
public class G6ServiceImpl implements IG6Service {

    private static final Log logger = LogFactory.getLog(G6ServiceImpl.class);
    OperateOption saveOption = OperateOption.create();

    //费用报销单
    @Override
    public void payForexpense(DynamicObject bill) {
        String g6_url = System.getProperty("g6.url");
        String basicAuthUserName = System.getProperty("g6.user");
        SortedMap<String, Object> map = new TreeMap<String, Object>();
        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "费用报销单G6");
        log.put("url", g6_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        long id = bill.getLong("id");
        map.put("ERPID", id);//唯一标识符
        map.put("FMCLSNO", "EPMS004");//付款业务类型
        map.put("ERPNO", bill.get("billno"));//唯一标识编号
        map.put("PAYTYPE", "3");//付款类别
        DynamicObject costcompany = bill.getDynamicObject("costcompany");//付款单位名称
        if (costcompany != null) {
            map.put("PAYCLTNAME", costcompany.get("name"));//付款单位名称
        }
        DynamicObject qeug_costdept = bill.getDynamicObject("qeug_costdept");//付款所属部门名称
        if (qeug_costdept != null) {
            map.put("CUSTNAME", qeug_costdept.get("name"));//付款所属部门名称
        }
        map.put("PAYACTDATE", "2024-12-10");//期望付款日期bill.getDate("repaymentdate")
        map.put("AMOUNT", bill.getBigDecimal("approveamount"));//付款金额
        map.put("ISPERSON", 1);//0：对公；1：对私 默认：对公,服务端自动生成
        map.put("EXPLAIN", bill.get("description"));//摘要（用途）
        map.put("KMNAME", "报销");//款项用途（名称）
        map.put("PAYINNER", 0);//是否内转
        map.put("URGENTFLAG", 0);//加急标识
        DynamicObject applier = bill.getDynamicObject("applier");//付款经办人
        if (applier != null) {
            map.put("PAYPERSON", applier.get("name"));//付款经办人
        }
        map.put("PAYDATE", bill.getDate("bizdate"));//制单日期2
        map.put("CHANNEL", "CCS");//付款单发起渠
        map.put("SETTLEMENTMODES", "0");//结算方式
        map.put("BUDGETFLAG", bill.get("qeug_budgetflag"));//预算类型
        map.put("FMCLS", 2);//业务类型
        map.put("ISWAIT", 0);//是否等通知
        map.put("DIR", 0);//0：主动；1：被动；
        map.put("DOCTYPE", 2);//单据类型/DOCTYPE：N：否；0:付款申请单；1:借款单；2:报销单

        DynamicObjectCollection accountEntryCollection = bill.getDynamicObjectCollection("accountentry");//收款信息分录
        DynamicObject accountEntry = accountEntryCollection.get(0);
        if (accountEntry != null) {
            DynamicObject paymode = accountEntry.getDynamicObject("paymode");
            if (paymode != null) {
                map.put("STCODE", paymode.get("number"));//付款方式
            }
            map.put("RECACTNO", accountEntry.get("payeraccount"));//收款方账号
            map.put("RECNAME", accountEntry.get("payeraccountname"));//收款方户名
            DynamicObject payerbank = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank != null) {
                map.put("RECBANKNO", payerbank.get("number"));//收款方支行编码
            }
            DynamicObject payerbank1 = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank1 != null) {
                map.put("RECBANKNAME", payerbank1.get("name"));//收款方支行名称
            }
            DynamicObject accountcurrency = accountEntry.getDynamicObject("accountcurrency");//币种
            if (accountcurrency != null) {
                map.put("CURRENCYNO", accountcurrency.get("number"));//币种
            }
            String payertype = accountEntry.getString("payertype");//收款人类型
            if (payertype.equals("bd_supplier")) {
                //收款人类型为供应商
                DynamicObject qeug_payernumber = accountEntry.getDynamicObject("supplier");//供应商
                if (qeug_payernumber != null) {
                    map.put("RELCORPNO", qeug_payernumber.getString("number"));//客商编码
                } else {
                    log.put("responsebody", "客商为空");
                }
            } else {
                DynamicObject payer = accountEntry.getDynamicObject("payer");//人员
                if (payer != null) {
                    map.put("RELCORPNO", payer.getString("number"));//客商编码
                } else {
                    log.put("responsebody", "客商为空");
                }
            }
        }

        String toXml = FacadeHelper.mapToXml(map, "data", "item");
        log.put("mainstring", toXml);
        String xml = FacadeHelper.perfectXml(toXml, bill);
        String auth = getAuth();
        String res = doPost(auth, xml);
        log.put("responsebody", res);
        //解析是否传送成功，流程挂起/是否重新审批等
        try {
            // 解析外层JSON
            JSONObject outerJson = JSONObject.parseObject(res);
            String xmlContent = outerJson.getString("returnMessage");

            // 使用XPath直接解析XML
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            String resultCode = xpath.evaluate("/fdlk/resultCode", source);

            if ("000000".equals(resultCode)) {
                log.put("pdesc", "成功");
                FacadeHelper.apiLog(log);
                bill.set("qeug_istog6", true);
                saveOption.setVariableValue("ignoreValidation", String.valueOf(true));//绕过网络互斥操作
                SaveServiceHelper.saveOperate("er_tripreimbursebill", new DynamicObject[]{bill}, OperateOption.create());
            } else {
                log.put("pdesc", "失败");
                FacadeHelper.apiLog(log);
            }
        } catch (Exception e) {
            log.put("pdesc", "失败，解析异常");
            FacadeHelper.apiLog(log);
        }
    }

    //差旅报销单
    @Override
    public void payForTravel(DynamicObject bill) {
        String g6_url = System.getProperty("g6.url");
        String basicAuthUserName = System.getProperty("g6.user");
        SortedMap<String, Object> map = new TreeMap<String, Object>();
        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "差旅报销单G6");
        log.put("url", g6_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        long id = bill.getLong("id");
        map.put("ERPID", id);//唯一标识符
        map.put("ERPNO", bill.get("billno"));//唯一标识编号
        map.put("FMCLSNO", "EPMS004");//付款业务类型
        DynamicObject costcompany = bill.getDynamicObject("costcompany");//付款单位名称
        if (costcompany != null) {
            map.put("PAYCLTNAME", costcompany.get("name"));//付款单位名称
        }
        DynamicObject qeug_costdept = bill.getDynamicObject("qeug_costdept");//付款所属部门名称
        if (qeug_costdept != null) {
            map.put("CUSTNAME", qeug_costdept.get("name"));//付款所属部门名称
        }
        map.put("PAYACTDATE", "2024-12-10");//期望付款日期bill.getDate("repaymentdate")
        map.put("AMOUNT", bill.getBigDecimal("approveamount"));//付款金额
        map.put("ISPERSON", 1);//0：对公；1：对私 默认：对公,服务端自动生成
        map.put("EXPLAIN", bill.get("description"));//摘要（用途）
        map.put("KMNAME", "报销");//款项用途（名称）流出
        map.put("PAYINNER", 0);//是否内转
        map.put("URGENTFLAG", 0);//加急标识
        DynamicObject applier = bill.getDynamicObject("applier");//付款经办人
        if (applier != null) {
            map.put("PAYPERSON", applier.get("name"));//付款经办人
        }
        map.put("PAYDATE", bill.getDate("bizdate"));//制单日期
        map.put("CHANNEL", "CCS");//付款单发起渠
        map.put("SETTLEMENTMODES", "0");//结算方式
        map.put("BUDGETFLAG", bill.get("qeug_budgetflag"));//预算类型
        map.put("FMCLS", 2);//业务类型
        map.put("ISWAIT", 0);//是否等通知
        map.put("DIR", 0);//0：主动；1：被动；
        map.put("DOCTYPE", 2);//单据类型/DOCTYPE：N：否；0:付款申请单；1:借款单；2:报销单
//        map.put("KMNAME", bill.getDynamicObject("qeug_kmname").get("name"));//款项用途（名称）
//            map.put("ITEMTID","EPMS004");//资金计划行项目号
//            map.put("CONTRACTNO",0);//业务合同编号
//            map.put("MEMO",bill.getDynamicObjectCollection("").get(0).get(""));//备注
//            map.put("PROJECTNAME",0);//投资项目

        DynamicObjectCollection accountEntryCollection = bill.getDynamicObjectCollection("accountentry");//收款信息分录
        DynamicObject accountEntry = accountEntryCollection.get(0);
        if (accountEntry != null) {
            DynamicObject paymode = accountEntry.getDynamicObject("paymode");
            if (paymode != null) {
                map.put("STCODE", paymode.get("number"));//付款方式
            }
            map.put("PAYTYPE", "3");//付款类别
            map.put("RECACTNO", accountEntry.get("payeraccount"));//收款方账号
            map.put("RECNAME", accountEntry.get("payeraccountname"));//收款方户名
            DynamicObject payerbank = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank != null) {
                map.put("RECBANKNO", payerbank.get("number"));//收款方支行编码
            }
            DynamicObject payerbank1 = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank1 != null) {
                map.put("RECBANKNAME", payerbank1.get("name"));//收款方支行名称
            }
            DynamicObject accountcurrency = accountEntry.getDynamicObject("accountcurrency");//币种
            if (accountcurrency != null) {
                map.put("CURRENCYNO", accountcurrency.get("number"));//币种
            }
            String payertype = accountEntry.getString("payertype");//收款人类型
            if (payertype.equals("bd_supplier")) {
                //收款人类型为供应商
                DynamicObject qeug_payernumber = accountEntry.getDynamicObject("supplier");//供应商
                if (qeug_payernumber != null) {
                    map.put("RELCORPNO", qeug_payernumber.getString("number"));//客商编码

                } else {
                    log.put("responsebody", "客商为空");
                }
            } else {
                DynamicObject payer = accountEntry.getDynamicObject("payer");//人员
                if (payer != null) {
                    map.put("RELCORPNO", payer.getString("number"));//客商编码
                } else {
                    log.put("responsebody", "客商为空");
                }

            }
        }

        String toXml = FacadeHelper.mapToXml(map, "data", "item");
        log.put("mainstring", toXml);
        String xml = FacadeHelper.perfectXml(toXml, bill);
        String auth = getAuth();
        String res = doPost(auth, xml);
        log.put("responsebody", res);
        //解析是否传送成功，流程挂起/是否重新审批等
        try {
            // 解析外层JSON
            JSONObject outerJson = JSONObject.parseObject(res);
            String xmlContent = outerJson.getString("returnMessage");

            // 使用XPath直接解析XML
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            String resultCode = xpath.evaluate("/fdlk/resultCode", source);

            if ("000000".equals(resultCode)) {
                log.put("pdesc", "成功");
                FacadeHelper.apiLog(log);
                bill.set("qeug_istog6", true);
                saveOption.setVariableValue("ignoreValidation", String.valueOf(true));//绕过网络互斥操作
                SaveServiceHelper.saveOperate("er_tripreimbursebill", new DynamicObject[]{bill}, OperateOption.create());
            } else {
                log.put("pdesc", "失败");
                FacadeHelper.apiLog(log);
            }
        } catch (Exception e) {
            log.put("pdesc", "失败，解析异常");
            FacadeHelper.apiLog(log);
        }
    }

    //借款单
    @Override
    public void payForDailyLoan(DynamicObject bill) {
        String g6_url = System.getProperty("g6.url");
        String basicAuthUserName = System.getProperty("g6.user");
        SortedMap<String, Object> map = new TreeMap<String, Object>();
        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "借款单G6");
        log.put("url", g6_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        long id = bill.getLong("id");
        map.put("ERPID", id);//唯一标识符
        map.put("FMCLSNO", "EPMS004");//付款业务类型
        map.put("ERPNO", bill.get("billno"));//唯一标识编号
        map.put("PAYTYPE", bill.getString("qeug_paytype"));//付款类别
        DynamicObject costcompany = bill.getDynamicObject("costcompany");//付款单位名称
        if (costcompany != null) {
            map.put("PAYCLTNAME", costcompany.get("name"));//付款单位名称
        }
        DynamicObject qeug_costdept = bill.getDynamicObject("qeug_costdept");//付款所属部门名称
        if (qeug_costdept != null) {
            map.put("CUSTNAME", qeug_costdept.get("name"));//付款所属部门名称
        }
        Date repaymentDate = bill.getDate("repaymentdate");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = dateFormat.format(repaymentDate);
        map.put("PAYACTDATE", formattedDate);//期望付款日期bill.getDate("repaymentdate")
        map.put("AMOUNT", bill.getBigDecimal("approveamount"));//付款金额
        map.put("ISPERSON", 1);//0：对公；1：对私 默认：对公,服务端自动生成
        map.put("EXPLAIN", bill.get("description"));//摘要（用途）
        DynamicObject qeug_kmname = bill.getDynamicObject("qeug_kmname");//款项用途
        if (qeug_kmname != null) {
            map.put("KMNAME", qeug_kmname.getString("name"));//款项用途（名称）
        }
        map.put("PAYINNER", 0);//是否内转
        map.put("URGENTFLAG", 0);//加急标识
        DynamicObject applier = bill.getDynamicObject("applier");//付款经办人
        if (applier != null) {
            map.put("PAYPERSON", applier.get("name"));//付款经办人
        }
        map.put("PAYDATE", bill.getDate("bizdate"));//制单日期2
        map.put("CHANNEL", "CCS");//付款单发起渠
        map.put("SETTLEMENTMODES", "0");//结算方式
        map.put("BUDGETFLAG", bill.get("qeug_budgetflag"));//预算类型
        map.put("FMCLS", 2);//业务类型
        map.put("ISWAIT", 0);//是否等通知
        map.put("DIR", 0);//0：主动；1：被动；
        map.put("DOCTYPE", 1);//单据类型/DOCTYPE：N：否；0:付款申请单；1:借款单；2:报销单

        DynamicObjectCollection accountEntryCollection = bill.getDynamicObjectCollection("accountentry");//收款信息分录
        DynamicObject accountEntry = accountEntryCollection.get(0);
        if (accountEntry != null) {
            DynamicObject paymode = accountEntry.getDynamicObject("paymode");
            if (paymode != null) {
                map.put("STCODE", paymode.get("number"));//付款方式
            }
            map.put("RECACTNO", accountEntry.get("payeraccount"));//收款方账号
            map.put("RECNAME", accountEntry.get("payeraccountname"));//收款方户名
            DynamicObject payerbank = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank != null) {
                map.put("RECBANKNO", payerbank.get("number"));//收款方支行编码
            }
            DynamicObject payerbank1 = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank1 != null) {
                map.put("RECBANKNAME", payerbank1.get("name"));//收款方支行名称
            }
            DynamicObject accountcurrency = accountEntry.getDynamicObject("accountcurrency");//币种
            if (accountcurrency != null) {
                map.put("CURRENCYNO", accountcurrency.get("number"));//币种
            }
            String payertype = accountEntry.getString("payertype");//收款人类型
            if (payertype.equals("bd_supplier")) {
                //收款人类型为供应商
                DynamicObject qeug_payernumber = accountEntry.getDynamicObject("supplier");//供应商
                if (qeug_payernumber != null) {
                    map.put("RELCORPNO", qeug_payernumber.getString("number"));//客商编码

                } else {
                    log.put("responsebody", "客商为空");
                }
            } else {
                DynamicObject payer = accountEntry.getDynamicObject("payer");//人员
                if (payer != null) {
                    map.put("RELCORPNO", payer.getString("number"));//客商编码
                } else {
                    log.put("responsebody", "客商为空");
                }
            }
        }

        String toXml = FacadeHelper.mapToXml(map, "data", "item");
        log.put("mainstring", toXml);
        String xml = FacadeHelper.perfectXml(toXml, bill);
        String auth = getAuth();
        String res = doPost(auth, xml);
        log.put("responsebody", res);
        //解析是否传送成功，流程挂起/是否重新审批等
        try {
            // 解析外层JSON
            JSONObject outerJson = JSONObject.parseObject(res);
            String xmlContent = outerJson.getString("returnMessage");

            // 使用XPath直接解析XML
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            String resultCode = xpath.evaluate("/fdlk/resultCode", source);

            if ("000000".equals(resultCode)) {
                log.put("pdesc", "成功");
                FacadeHelper.apiLog(log);
                bill.set("qeug_istog6", true);
                saveOption.setVariableValue("ignoreValidation", String.valueOf(true));//绕过网络互斥操作
                SaveServiceHelper.saveOperate("er_tripreimbursebill", new DynamicObject[]{bill}, OperateOption.create());
            } else {
                log.put("pdesc", "失败");
                FacadeHelper.apiLog(log);
            }
        } catch (Exception e) {
            log.put("pdesc", "失败，解析异常");
            FacadeHelper.apiLog(log);
        }
    }

    //资金计划
    @Override
    public void payFundPlan(DynamicObject bill) {
        String g6_url = System.getProperty("g6.url");
        String basicAuthUserName = System.getProperty("g6.user");
        SortedMap<String, Object> map = new TreeMap<String, Object>();
        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("url", g6_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        long id = bill.getLong("id");
        DynamicObject billType = bill.getDynamicObject("qeug_billtype");//单据类型
        String billTypeNumber = billType.getString("number");
        //资金计划和资金计划调整单据类型为月度支出和月度收入计划才走G6
        if ("qeug_fundplan_03".equals(billTypeNumber) || "qeug_fundplan_04".equals(billTypeNumber)) {
            //周支出和周收入计划不走G6
            return;
        }
        if ("qeug_fundadjust_01".equals(billTypeNumber) || "qeug_fundadjust_02".equals(billTypeNumber)) {
            log.put("operationModule", "资金计划调整G6");
        } else {
            log.put("operationModule", "资金计划G6");
        }
        map.put("ERP_INS_ID", bill.getString("billno"));//ERP端数据唯一标识
        DynamicObject org = bill.getDynamicObject("org");//公司
        if (org != null) {
            map.put("CLTNAME", org.getString("name"));
        }
        DynamicObject qeug_costdept = bill.getDynamicObject("qeug_costdept");//一级承担部门
        if (qeug_costdept != null) {
            map.put("CUSTNAME", qeug_costdept.getString("name"));
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        DynamicObject entryEntity1 = bill.getDynamicObjectCollection("entryentity").get(0);
        Date date = entryEntity1.getDate("qeug_planpaydate");//预算日期
        String formattedDate = dateFormat.format(date);
        map.put("BUDG_DATE", formattedDate);//预算日期
        map.put("BUDG_TYPE", "MM");//预算类型
        map.put("IS_AUDIT", 0);//是否审批
        DynamicObject qeug_currencyfie = bill.getDynamicObject("qeug_currencyfie");//表头币别
        if (qeug_currencyfie != null) {
            String currencyNumber = qeug_currencyfie.getString("number");
            map.put("CURRENCYNO", currencyNumber);//币别
        } else {
            map.put("CURRENCYNO", "CNY");//币别
        }

        //第二层嵌套
        List<Map<String, Object>> items = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();
        if ("qeug_fundadjust_01".equals(billTypeNumber) || "qeug_fundadjust_02".equals(billTypeNumber)) {
            //资金计划调整
            BigDecimal qeug_ysbankamount = entryEntity1.getBigDecimal("qeug_newbankamount");//调整后银行存款
            BigDecimal qeug_yshpamount = entryEntity1.getBigDecimal("qeug_newyshpamount");//调整后承兑汇票
            BigDecimal qeug_ysxyzamount = entryEntity1.getBigDecimal("qeug_newxyzamount");//调整后信用证
            item.put("AMOUNT", qeug_ysbankamount.add(qeug_yshpamount.add(qeug_ysxyzamount)));//总金额(总金额（现金金额+票据金额+信用证额），没值默认0
            item.put("CASHAMOUNT", qeug_ysbankamount);//现金金额
            item.put("BILLAMOUNT", qeug_yshpamount);//票据金额
            item.put("LCAMOUNT", qeug_ysxyzamount);//信用证金额
        } else {
            //资金计划
            BigDecimal qeug_ysbankamount = entryEntity1.getBigDecimal("qeug_ysbankamount");//初始银行存款
            BigDecimal qeug_yshpamount = entryEntity1.getBigDecimal("qeug_yshpamount");//初始承兑汇票
            BigDecimal qeug_ysxyzamount = entryEntity1.getBigDecimal("qeug_ysxyzamount");//初始信用证
            item.put("AMOUNT", qeug_ysbankamount.add(qeug_yshpamount.add(qeug_ysxyzamount)));//总金额(总金额（现金金额+票据金额+信用证额），没值默认0
            item.put("CASHAMOUNT", qeug_ysbankamount);//现金金额
            item.put("BILLAMOUNT", qeug_yshpamount);//票据金额
            item.put("LCAMOUNT", qeug_ysxyzamount);//信用证金额
        }
        item.put("BUDG_DATE", formattedDate);//预算日期
        item.put("DETAIL_ID", id);//数据唯一标识
        DynamicObject qeug_fundsuse = entryEntity1.getDynamicObject("qeug_fundsuse");//款项用途（名称）
        if (qeug_fundsuse != null) {
            String fundsUseName = qeug_fundsuse.getString("name");
            if ("qeug_fundplan_01".equals(billTypeNumber) || "qeug_fundadjust_01".equals(billTypeNumber)) {
                //月度支出计划
                item.put("KMDIR", 1);//资金方向
                item.put("KMNAME", fundsUseName);//款项用途（名称）流出
            } else {
                //月度收入计划
                item.put("KMDIR", 0);//资金方向
                item.put("KMNAME", fundsUseName);//款项用途（名称）流入
            }
        }
        item.put("IS_DETAIL", "1");//是否资金计划

        //第三层嵌套
        List<Map<String, Object>> itemDetails = new ArrayList<>();
        DynamicObjectCollection entryEntities = bill.getDynamicObjectCollection("entryentity");
        for (DynamicObject entryEntity : entryEntities) {
            Map<String, Object> itemDetail = new HashMap<>();
            itemDetail.put("ITEMID", entryEntity.getLong("id"));//资金计划行项目号
            String qeug_paytype = entryEntity.getString("qeug_paytype");//付款类别
            if (StringUtils.isNotBlank(qeug_paytype)) {
                itemDetail.put("PAYTYPE", qeug_paytype);
            }
            itemDetail.put("ACT_DATE", formattedDate);//执行日期
            itemDetail.put("SUMMARYAND", entryEntity.getString("qeug_remark"));//摘要
            DynamicObject customerSupplier = null;//客商
            if ("qeug_fundplan_01".equals(billTypeNumber) || "qeug_fundadjust_01".equals(billTypeNumber)) {
                //资金计划和资金计划调整的月度支出计划
                DynamicObject qeug_supplier = entryEntity.getDynamicObject("qeug_supplier");//收款单位-供应商
                customerSupplier = BusinessDataServiceHelper.
                        loadSingle("bd_supplier", new QFilter("number", "=", qeug_supplier.getString("number")).toArray());//客商-供应商
            } else if ("qeug_fundplan_02".equals(billTypeNumber) || "qeug_fundadjust_02".equals(billTypeNumber)) {
                //资金计划和资金计划调整的月度收入计划
                DynamicObject qeug_customer = entryEntity.getDynamicObject("qeug_customer");//收款单位-客户
                customerSupplier = BusinessDataServiceHelper.
                        loadSingle("bd_customer", new QFilter("number", "=", qeug_customer.getString("number")).toArray());//客商-客户
            }
            if (customerSupplier != null) {
                DynamicObjectCollection entry_bank = customerSupplier.getDynamicObjectCollection("entry_bank");//银行信息
                for (DynamicObject bankEntry : entry_bank) {
                    boolean isdefault_bank = bankEntry.getBoolean("isdefault_bank");//是否默认
                    if (isdefault_bank) {
                        DynamicObject bank = bankEntry.getDynamicObject("bank");//开户银行
                        itemDetail.put("CLTNAME", customerSupplier.getString("name"));//客商里的信息：对应付款维护往来单位
                        itemDetail.put("CLTNO", customerSupplier.getString("number"));//客商里的信息：往来单位名称
                        itemDetail.put("ACCOUNTNO", bankEntry.getString("bankaccount"));//银行账号/ 客商里的信息：对应付款维护常用账户
                        itemDetail.put("ACCOUNTNAME", bank.getString("name"));//账户名称/ 客商里的信息：常用帐号名称
                    }
                }
            }
            if ("qeug_fundadjust_01".equals(billTypeNumber) || "qeug_fundadjust_02".equals(billTypeNumber)) {
                //资金计划调整
                BigDecimal qeug_ysbankamount1 = entryEntity.getBigDecimal("qeug_newbankamount");// 初始银行存款
                BigDecimal qeug_yshpamount1 = entryEntity.getBigDecimal("qeug_newyshpamount");// 初始承兑汇票
                BigDecimal qeug_ysxyzamount1 = entryEntity.getBigDecimal("qeug_newxyzamount");// 初始信用证
                itemDetail.put("CASHAMOUNT", qeug_ysbankamount1);//现金金额
                itemDetail.put("BILLAMOUNT", qeug_yshpamount1);//票据金额
                itemDetail.put("LCAMOUNT", qeug_ysxyzamount1);//信用证金额
            } else {
                //资金计划
                BigDecimal qeug_ysbankamount1 = entryEntity.getBigDecimal("qeug_ysbankamount");// 初始银行存款
                BigDecimal qeug_yshpamount1 = entryEntity.getBigDecimal("qeug_yshpamount");// 初始承兑汇票
                BigDecimal qeug_ysxyzamount1 = entryEntity.getBigDecimal("qeug_ysxyzamount");// 初始信用证
                itemDetail.put("CASHAMOUNT", qeug_ysbankamount1);//现金金额
                itemDetail.put("BILLAMOUNT", qeug_yshpamount1);//票据金额
                itemDetail.put("LCAMOUNT", qeug_ysxyzamount1);//信用证金额
            }
            DynamicObject qeug_person = entryEntity.getDynamicObject("qeug_person");//业务员
            if (qeug_person != null) {
                itemDetail.put("INPUTOR", qeug_person.getString("name"));
            }
            itemDetails.add(itemDetail);
        }
        item.put("itemDetail", itemDetails);

        items.add(item);
        map.put("item", items);

        String toXml = FacadeHelper.mapToNestedXml(map, "cfb");
        log.put("mainstring", toXml);
        String xml = FacadeHelper.payFundPlanXml(toXml, bill);
        String auth = getAuth();
        String res = doPost(auth, xml);
        log.put("responsebody", res);
        try {
            // 解析外层JSON
            JSONObject outerJson = JSONObject.parseObject(res);
            String xmlContent = outerJson.getString("returnMessage");

            // 使用XPath直接解析XML
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            String resultCode = xpath.evaluate("/fdlk/resultCode", source);

            if ("000000".equals(resultCode)) {
                log.put("pdesc", "成功");
                FacadeHelper.apiLog(log);
                DynamicObjectCollection entryEntities2 = bill.getDynamicObjectCollection("entryentity");
                entryEntities2.forEach(entry -> entry.set("qeug_isg6", true));
                saveOption.setVariableValue("ignoreValidation", String.valueOf(true));//绕过网络互斥操作
                SaveServiceHelper.saveOperate("qeug_fundplan", new DynamicObject[]{bill}, OperateOption.create());
            } else {
                log.put("pdesc", "失败");
                FacadeHelper.apiLog(log);
            }
        } catch (Exception e) {
            log.put("pdesc", "失败，解析异常");
            FacadeHelper.apiLog(log);
        }
    }

    //付款申请单
    @Override
    public void paymentApplication(DynamicObject bill) {
        String g6_url = System.getProperty("g6.url");
        String basicAuthUserName = System.getProperty("g6.user");
        SortedMap<String, Object> map = new TreeMap<String, Object>();
        //日志
        HashMap<String, Object> log = new HashMap<>();
        log.put("operationModule", "付款申请G6");
        log.put("url", g6_url);
        log.put("user", basicAuthUserName);
        log.put("mode", "POST");
        log.put("action", "");
        log.put("opdate", new Date());
        long id = bill.getLong("id");
        map.put("ERPID", id);//唯一标识符
        map.put("ERPNO", bill.get("billno"));//唯一标识编号
        map.put("FMCLSNO", "EPMS004");//付款业务类型
        map.put("PAYTYPE", bill.getString("qeug_paytype"));//付款类别
        DynamicObject costcompany = bill.getDynamicObject("costcompany");//付款单位名称
        if (costcompany != null) {
            map.put("PAYCLTNAME", costcompany.get("name"));//付款单位名称
        }
        DynamicObject qeug_costdept = bill.getDynamicObject("qeug_costdept");//付款所属部门名称
        if (qeug_costdept != null) {
            map.put("CUSTNAME", qeug_costdept.get("name"));//付款所属部门名称
        }
        map.put("PAYACTDATE", "2024-12-10");//期望付款日期bill.getDate("repaymentdate")
        map.put("AMOUNT", bill.getBigDecimal("approveamount"));//付款金额
        map.put("ISPERSON", 0);//0：对公；1：对私 默认：对公,服务端自动生成
        map.put("EXPLAIN", bill.get("description"));//摘要（用途）
        DynamicObject qeug_usefunds = bill.getDynamicObject("qeug_usefunds");//款项用途
        if (qeug_usefunds != null) {
            map.put("KMNAME", qeug_usefunds.get("name"));//款项用途（名称）//现金流、流出
        }
        map.put("PAYINNER", 0);//是否内转
        map.put("URGENTFLAG", 0);//加急标识
        map.put("CONTRACTNO", bill.get("qeug_contractnum"));//业务合同编号
        map.put("MEMO", bill.getDynamicObjectCollection("expenseentryentity").get(0).get("remark"));//备注
        DynamicObject applier = bill.getDynamicObject("applier");//付款经办人
        if (applier != null) {
            map.put("PAYPERSON", applier.get("name"));//付款经办人
        }
        map.put("PAYDATE", bill.getDate("bizdate"));//制单日期
        map.put("CHANNEL", "CCS");//付款单发起渠
        map.put("SETTLEMENTMODES", bill.getString("qeug_plantype"));//结算方式/计划类型
        DynamicObject qeug_settlementtype = bill.getDynamicObject("qeug_settlementtype");//付款方式
        if (qeug_settlementtype != null) {
            map.put("STCODE", qeug_settlementtype.getString("number"));//付款方式
        }
        boolean qeug_budgettype = bill.getBoolean("qeug_budgettype");//是否引用资金计划
        if (qeug_budgettype) {
            map.put("BUDGETFLAG", 1);//0：预算外；1：预算内
            map.put("ITEMTID", bill.getString("qeug_fundplanentry"));//资金计划行号
        } else {
            map.put("BUDGETFLAG", 0);//0：预算外；1：预算内
        }
        map.put("FMCLS", 2);//业务类型
        map.put("ISWAIT", 0);//是否等通知
        map.put("PROJECTNAME", bill.getString("qeug_invesproject"));//投资项目
        map.put("DIR", 0);//0：主动；1：被动；
        map.put("DOCTYPE", 0);//单据类型/DOCTYPE：N：否；0:付款申请单；1:借款单；2:报销单
        map.put("ORIGERPNO", "");//原始付款申请单号
        map.put("PURPOSE", bill.getDynamicObjectCollection("expenseentryentity").get(0).get("remark"));//付款说明

        DynamicObjectCollection accountEntryCollection = bill.getDynamicObjectCollection("accountentry");//收款信息分录
        DynamicObject accountEntry = accountEntryCollection.get(0);
        if (accountEntry != null) {
            map.put("RECACTNO", accountEntry.get("payeraccount"));//收款方账号
            map.put("RECNAME", accountEntry.get("payeraccountname"));//收款方户名
            DynamicObject payerbank = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank != null) {
                map.put("RECBANKNO", payerbank.get("number"));//收款方支行编码
            }
            DynamicObject payerbank1 = accountEntry.getDynamicObject("payerbank");//收款方支行
            if (payerbank1 != null) {
                map.put("RECBANKNAME", payerbank1.get("name"));//收款方支行名称
            }
            DynamicObject accountcurrency = accountEntry.getDynamicObject("accountcurrency");//币种
            if (accountcurrency != null) {
                map.put("CURRENCYNO", accountcurrency.get("number"));//币种
            }
            String payerType = accountEntry.getString("payertype");//收款人类型
            DynamicObject customerSupplier = null;//客商
            if ("bd_supplier".equals(payerType)) {
                DynamicObject qeug_payernumsup = accountEntry.getDynamicObject("qeug_payernumsup");//供应商
                customerSupplier = BusinessDataServiceHelper.
                        loadSingle("bd_supplier", new QFilter("number", "=", qeug_payernumsup.getString("number")).toArray());//客商-供应商
            } else if ("bd_customer".equals(payerType)) {
                DynamicObject qeug_payernumcus = accountEntry.getDynamicObject("qeug_payernumcus");//客户
                customerSupplier = BusinessDataServiceHelper.
                        loadSingle("bd_customer", new QFilter("number", "=", qeug_payernumcus.getString("number")).toArray());//客商-客户
            }
            if (customerSupplier == null) {
                log.put("responsebody", "客商为空");
                map.put("RELCORPNO", "");//客商编码
            } else {
                map.put("RELCORPNO", customerSupplier.getString("number"));//客商编码
            }
        }

        String toXml = FacadeHelper.mapToXml(map, "data", "item");
        log.put("mainstring", toXml);
        String xml = FacadeHelper.paymentApplicationXml(toXml, bill);
        String auth = getAuth();
        String res = doPost(auth, xml);
        log.put("responsebody", res);
        //解析是否传送成功，流程挂起/是否重新审批等
        try {
            // 解析外层JSON
            JSONObject outerJson = JSONObject.parseObject(res);
            String xmlContent = outerJson.getString("returnMessage");

            // 使用XPath直接解析XML
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            String resultCode = xpath.evaluate("/fdlk/resultCode", source);

            if ("000000".equals(resultCode)) {
                log.put("pdesc", "成功");
                FacadeHelper.apiLog(log);
                bill.set("qeug_istog6", true);//是否已推送G6按钮
                bill.set("head_paydate", new Date());//付款日期，方便后续生成凭证
                bill.set("billstatus", "F");//直接变为等待付款，方便后续生成凭证
                saveOption.setVariableValue("ignoreValidation", String.valueOf(true));//绕过网络互斥操作
                SaveServiceHelper.saveOperate("er_publicreimbursebill", new DynamicObject[]{bill}, OperateOption.create());
                logger.info("付款申请单保存后调用扣减预算与生成凭证");
                OperationResult operationResult = SaveServiceHelper.saveOperate("dobuget", "er_publicreimbursebill", new DynamicObject[]{bill}, saveOption);//调用扣减预算操作
                boolean success = operationResult.isSuccess();
                if (success) {
                    logger.info("付款申请单扣减预算成功生成凭证");
                    String id1 = String.valueOf(bill.get("id"));
                    OperationServiceHelper.executeOperate("generatevoucher", "er_publicreimbursebill", new Object[]{id1}, saveOption);//调用生成凭证操作
                }
            } else {
                log.put("pdesc", "失败");
                FacadeHelper.apiLog(log);
            }
        } catch (Exception e) {
            log.put("pdesc", "失败，解析异常");
            FacadeHelper.apiLog(log);
        }
    }

    private String getAuth() {
        String basicAuthUserName = System.getProperty("g6.user");
        String basicAuthPassword = System.getProperty("g6.password");

        String basic = basicAuthUserName + ":" + basicAuthPassword;
        return Base64Utils.encodeToString(basic.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 调用G6接口
     *
     * @param auth
     * @param json
     * @return
     */
    private String doPost(String auth, String json) {
        String g6_url = System.getProperty("g6.url");
        String send_standard = HttpRequest.post(g6_url)
                .header("Authorization", "Basic " + auth)
                .body(json)
                .execute().body();
        return send_standard;
    }
}
